﻿using ApplicationBase.Core.Context;
using IdentityService.Domain.Aggregates.RoleAggregate;
using IdentityService.Domain.Repositories;
using System.Data;

namespace IdentityService.Domain.Services
{
    public interface IRoleService
    {
        Task<CreateRoleResultModel> CreateRoleAsync(string name, string appName, string description = "");
        Task<DeleteRoleResult> DeleteRoleAsync(long id);
        Task<ModifyRoleResult> ModifyRoleAsync(long id, string name, string description = "");
        Task<ChangePermitsResult> ChangePermitsAsync(long id, List<long> permitIds);
    }

    public class RoleService : IRoleService
    {
        private readonly IRoleRepository _repository;
        private readonly IServiceContext _serviceContext;
        public RoleService(IRoleRepository repository, IServiceContext serviceContext) 
            => (_repository, _serviceContext) = (repository, serviceContext);

        public async Task<CreateRoleResultModel> CreateRoleAsync(string name, string appName, string description = "")
        {
            if(await _repository.CheckExistByNameAsync(name))
                return new CreateRoleResultModel { Result = CreateRoleResult.NameExisted };

            var role = new Role(_serviceContext.GenerateId(), name, appName, description);
            await _repository.AddAsync(role);

            return new CreateRoleResultModel
            {
                Result = CreateRoleResult.Success,
                Data = role
            };
        }

        public async Task<DeleteRoleResult> DeleteRoleAsync(long id)
        {
            var role = await _repository.FindByIdIncludeAllAsync(id);
            if (role == null) return DeleteRoleResult.IdNotFound;
            if (role.UserAccounts.Count() > 0) return DeleteRoleResult.HasUserAccountCanNotDelete;

            _repository.Delete(role);
            return DeleteRoleResult.Success;
        }

        public async Task<ModifyRoleResult> ModifyRoleAsync(long id, string name, string description = "")
        {
            var dbRole = await _repository.FindByIdAsync(id);
            if (dbRole == null) return ModifyRoleResult.IdNotFound;
            if (dbRole.Name != name && await _repository.CheckExistByNameAsync(name))
                return ModifyRoleResult.NameExisted;

            dbRole.Modify(name, description);
            return ModifyRoleResult.Success;
        }

        public async Task<ChangePermitsResult> ChangePermitsAsync(long id, List<long> permitIds)
        {
            var dbRole = await _repository.FindByIdIncludePermitsAsync(id);
            if (dbRole == null) return ChangePermitsResult.IdNotFound;

            //删除已失效的通行证
            var needDeleteList = dbRole.Permits.Where(it => !permitIds.Contains(it.PermitId)).ToList();
            foreach(var needDeleteItem in  needDeleteList)
            {
                dbRole.Permits.Remove(needDeleteItem);
            }

            //添加新的通行证
            var dbPermits = dbRole.Permits.Select(it => it.PermitId).ToList();
            var needAddList = permitIds.Where(it => !dbPermits.Contains(it)).ToList();
            foreach (var needAddId in needAddList)
            {
                var permit = new RolePermit(_serviceContext.GenerateId(), id, needAddId);
                dbRole.Permits.Add(permit);
            }

            return ChangePermitsResult.Success;
        }
    }

    public enum CreateRoleResult
    {
        Success,
        NameExisted
    }

    public class CreateRoleResultModel
    {
        public CreateRoleResult Result { get; set; }
        public Role? Data { get; set; }
    }

    public enum DeleteRoleResult
    {
        Success,
        IdNotFound,
        HasUserAccountCanNotDelete,
    }

    public enum ModifyRoleResult
    {
        Success,
        IdNotFound,
        NameExisted
    }

    public enum ChangePermitsResult
    {
        Success,
        IdNotFound
    }
}
